﻿/**
* @preserve Unobtrusive Knockout support library for jQuery
*
* @author Joel Thoms
* @modified Andrii Naidenko
* @version 1.1
*/

// USAGE SAMPLE:
// Choose a ticket class: <select id="tickets"></select>
// 
// $("#tickets").dataBind({
//     options: "tickets",
//     optionsCaption: "'Choose...'",
//     optionsText: "'name'",
//     value: "chosenTicket"
// });

(function ($)
{

    if (!$ || !$['fn']) throw new Error('jQuery library is required.');

    /**
    * Private method to recursively render key value pairs into a string
    *
    * @param {Object} options Object to render into a string.
    * @return {string} The string value of the object passed in.
    */
    function render(options)
    {
        var rendered = [];
        for (var key in options)
        {
            var val = options[key];
            if (val instanceof Array)
            {
                var arrStr = val.length > 0 ? ("'" + val.join("','") + "'") : "";
                rendered.push(key + ":[" + arrStr + "]");
            }
            else
            {
                switch (typeof val)
                {
                    case 'number': rendered.push(key + ':' + val); break;
                    case 'string': rendered.push(key + ':' + val); break;
                    case 'object': rendered.push(key + ':{' + render(val) + '}'); break;
                    case 'function': rendered.push(key + ':' + val.toString()); break;
                }
            }
        }
        return rendered.join(',');
    }

    /**
    * jQuery extension to handle unobtrusive Knockout data binding.
    *
    * @param {Object} options Object to render into a string.
    * @return {Object} A jQuery object.
    */
    $['fn']['dataBind'] = $['fn']['dataBind'] || function (options)
    {
        var optsArgs = Array.prototype.slice.call(arguments); // clone arguments

        return this['each'](function ()
        {
            var dataBindDefaults = $['fn']['dataBind']['defaults'];

            if (optsArgs.length > 0)
            {
                optsArgs[0] = $.extend({}, dataBindDefaults, optsArgs[0]);
            }
            else
            {
                optsArgs.push(dataBindDefaults);
            }

            var optsRendered = $.map(optsArgs, function (opts)
            {
                return render(opts);
            });

            var dataBindOptions = [];
            $.each(optsRendered, function (i, optsAttr)
            {
                if (optsAttr != null && optsAttr != '')
                {
                    dataBindOptions.push(optsAttr);
                }
            });

            if (dataBindOptions.length > 0)
            {
                $(this)['attr']('data-bind', dataBindOptions.join(', '));
            }
        });
    };

})(jQuery);
